CSRF (Cross-Site Request Forgery) একটি ওয়েব অ্যাপ্লিকেশন আক্রমণের পদ্ধতি, যেখানে একজন ব্যবহারকারীকে তাদের অজান্তেই একটি অননুমোদিত অনুরোধ পাঠাতে বাধ্য করা হয়।
Spring Security CSRF আক্রমণ প্রতিরোধে একটি বিল্ট-ইন CSRF Protection প্রদান করে, যা ডিফল্টভাবে সক্রিয় থাকে।
CSRF আক্রমণ কীভাবে কাজ করে?
- ব্যবহারকারী একটি নির্ভরযোগ্য সাইটে লগইন করে এবং একটি বৈধ সেশন তৈরি হয়।
- আক্রমণকারী একটি ম্যালিশিয়াস সাইট তৈরি করে এবং ব্যবহারকারীকে সেই সাইটটি ভিজিট করতে প্রলুব্ধ করে।
- ব্যবহারকারী যদি ম্যালিশিয়াস সাইটটি ভিজিট করেন, তবে সেই সাইট ব্যবহারকারীর বৈধ সেশনের মাধ্যমে অননুমোদিত অনুরোধ পাঠাতে পারে।
- এই অনুরোধের মাধ্যমে গুরুত্বপূর্ণ ডেটা পরিবর্তন বা অননুমোদিত কার্যক্রম সম্পন্ন হতে পারে।
Spring Security এর CSRF Protection কিভাবে কাজ করে?
Spring Security CSRF আক্রমণ প্রতিরোধে একটি টোকেন ভিত্তিক পদ্ধতি ব্যবহার করে।
CSRF টোকেনের মূলনীতি:
- প্রতিটি HTTP POST, PUT, DELETE অনুরোধের জন্য একটি CSRF টোকেন জেনারেট হয়।
- এই টোকেনটি অনুরোধের সাথে পাঠানো হয় (সাধারণত একটি হেডার বা হিডেন ইনপুট ফিল্ডের মাধ্যমে)।
- Spring Security অনুরোধে প্রাপ্ত টোকেন যাচাই করে।
- যদি টোকেন মেলে না, তবে অনুরোধ প্রত্যাখ্যান করা হয়।
Spring Security-তে CSRF Protection কনফিগারেশন:
1. ডিফল্ট CSRF Protection:
Spring Security Starter যুক্ত করলেই CSRF Protection ডিফল্টভাবে সক্রিয় থাকে।
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.anyRequest().authenticated()
)
.formLogin()
.and()
.csrf(); // CSRF Protection enabled by default
return http.build();
}
2. CSRF Token Generator:
Spring Security স্বয়ংক্রিয়ভাবে একটি CSRF টোকেন জেনারেট করে এবং HTML ফর্মে এটি যুক্ত করে।
HTML Example (Thymeleaf):
<form action="/update" method="post">
<input type="hidden" name="_csrf" value="${_csrf.token}" />
<button type="submit">Submit</button>
</form>
AJAX Example (JavaScript):
let csrfToken = document.querySelector('meta[name="_csrf"]').content;
let csrfHeader = document.querySelector('meta[name="_csrf_header"]').content;
fetch('/update', {
method: 'POST',
headers: {
[csrfHeader]: csrfToken,
'Content-Type': 'application/json'
},
body: JSON.stringify({ name: "John Doe" })
});
3. CSRF Disable (Optional):
কিছু নির্দিষ্ট ক্ষেত্রে, যেমন REST API যেখানে Stateless Authentication (JWT বা OAuth) ব্যবহার করা হয়, CSRF Protection নিষ্ক্রিয় করা যেতে পারে।
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeHttpRequests(auth -> auth
.anyRequest().authenticated()
)
.formLogin();
return http.build();
}
Spring Security CSRF Token যাচাই:
Spring Security টোকেন যাচাই করতে দুটি ধাপে কাজ করে:
- Token Generation: একটি CSRF টোকেন জেনারেট হয় এবং সেশনের সাথে যুক্ত থাকে।
- Token Validation: যখন অনুরোধ আসে, তখন প্রাপ্ত টোকেন সেশন থেকে প্রাপ্ত টোকেনের সাথে মেলে কিনা তা যাচাই করা হয়।
কখন CSRF Protection ব্যবহার করবেন?
CSRF Protection প্রয়োজন:
- Traditional Web Applications: যেখানে সেশন এবং ফর্ম-ভিত্তিক লগইন ব্যবহার হয়।
- Multi-Page Applications (MPA): যেখানে ব্যবহারকারী একই সেশনে একাধিক ফর্ম সাবমিট করতে পারেন।
CSRF Protection প্রয়োজন নেই:
- Stateless REST API: যেখানে JWT বা OAuth2 টোকেন ব্যবহার হয়।
- Public API: যেখানে ক্লায়েন্ট সার্ভার সাইড টোকেন যাচাইয়ের প্রয়োজন হয় না।
Spring Security এর CSRF Features এবং সুবিধা:
- Automatic Token Management: Spring Security স্বয়ংক্রিয়ভাবে CSRF টোকেন পরিচালনা করে।
- Custom CSRF Filter: আপনি চাইলে কাস্টম ফিল্টার ব্যবহার করতে পারেন।
- Granular Control: নির্দিষ্ট URL বা পদ্ধতির জন্য CSRF Protection চালু বা বন্ধ করা যায়।
- Integration with Thymeleaf: HTML টেমপ্লেট ইঞ্জিনের মাধ্যমে সহজে CSRF টোকেন ইন্টিগ্রেশন।
উদাহরণ: কাস্টম CSRF কনফিগারেশন
নির্দিষ্ট রিকোয়েস্টে CSRF Protection চালু/বন্ধ করা:
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf
.ignoringRequestMatchers("/api/**") // Disable CSRF for APIs
)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
);
return http.build();
}
Custom CSRF Token Repository:
Spring Security-তে CSRF টোকেন সংরক্ষণ করতে কাস্টম স্টোরেজ ব্যবহার করা যেতে পারে।
@Bean
public CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setSessionAttributeName("_custom_csrf");
return repository;
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf
.csrfTokenRepository(csrfTokenRepository())
)
.authorizeHttpRequests(auth -> auth
.anyRequest().authenticated()
);
return http.build();
}
উপসংহার:
Spring Security এর CSRF Protection একটি শক্তিশালী নিরাপত্তা ব্যবস্থা যা সাধারণ CSRF আক্রমণ থেকে ওয়েব অ্যাপ্লিকেশনকে রক্ষা করে। এটি সাধারণত ফর্ম-বেসড অ্যাপ্লিকেশন এবং সেশনের উপর নির্ভরশীল ওয়েবসাইটে কার্যকর। তবে Stateless REST API-এর ক্ষেত্রে এটি নিষ্ক্রিয় করাও যুক্তিযুক্ত হতে পারে।
CSRF Protection ব্যবহারের সময়:
- HTML ফর্মে
_csrfটোকেন যুক্ত করা। - AJAX রিকোয়েস্টের জন্য হেডারে টোকেন যোগ করা।
- কনফিগারেশন অনুযায়ী CSRF সঠিকভাবে সক্রিয় বা নিষ্ক্রিয় করা।
CSRF হল একটি সাধারণ ওয়েব নিরাপত্তা দুর্বলতা যেখানে একটি হ্যাকার বৈধ ব্যবহারকারীকে ঠকিয়ে একটি অবাঞ্ছিত বা ক্ষতিকারক অনুরোধ সম্পাদন করতে বাধ্য করে। এটি বিশেষত এমন ক্ষেত্রে ঘটে যখন ব্যবহারকারী সঠিকভাবে লগইন করা অবস্থায় থাকে এবং সেশনের সাথে যুক্ত একটি বৈধ সুরক্ষা টোকেন (Session Token) রয়েছে।
CSRF কীভাবে কাজ করে?
- Step 1:
- ব্যবহারকারী একটি নির্ভরযোগ্য ওয়েবসাইটে লগইন করে।
- ওয়েবসাইটটি একটি সক্রিয় সেশন বা সুরক্ষা টোকেন তৈরি করে যা ব্রাউজারের সাথে যুক্ত থাকে।
- Step 2:
- হ্যাকার ব্যবহারকারীকে একটি ক্ষতিকারক লিঙ্ক বা ফর্মে ক্লিক করাতে প্ররোচিত করে।
- Step 3:
- ব্যবহারকারী সেই লিঙ্কে ক্লিক করলে, হ্যাকার একটি HTTP রিকোয়েস্ট পাঠায় যেটি ব্যবহারকারীর সেশনের অধীনে প্রমাণীকৃত হয়।
- Step 4:
- ওয়েব সার্ভার সেই রিকোয়েস্টটি বৈধ মনে করে এবং ব্যবহারকারীর অনুমোদনের বাইরে একটি ক্ষতিকারক কাজ সম্পন্ন হয় (যেমন, অ্যাকাউন্ট ডিলিট করা বা অর্থ লেনদেন)।
CSRF প্রতিরোধ কেন প্রয়োজন?
- Unauthorized Action প্রতিরোধ:
- ব্যবহারকারীকে না জানিয়েই গুরুত্বপূর্ণ কাজ (যেমন, অর্থ স্থানান্তর, ডেটা মুছে ফেলা) সম্পন্ন হতে পারে।
- User Trust বজায় রাখা:
- CSRF আক্রমণ ব্যবহারকারীর এবং সার্ভারের মধ্যে বিশ্বাস নষ্ট করে।
- Sensitive Operations সুরক্ষিত করা:
- যেমন পাসওয়ার্ড পরিবর্তন, অর্থ লেনদেন, বা অ্যাকাউন্ট ডিলিট সুরক্ষিত রাখা।
- Web Application এর সুনাম রক্ষা করা:
- CSRF আক্রমণ ওয়েব অ্যাপ্লিকেশনের নিরাপত্তা প্রশ্নবিদ্ধ করতে পারে।
Spring Security এ CSRF Protection:
Spring Security ডিফল্টভাবে CSRF Protection সক্রিয় করে। এটি নিশ্চিত করে যে প্রতিটি HTTP POST, PUT, DELETE রিকোয়েস্টের সাথে একটি বৈধ CSRF টোকেন অন্তর্ভুক্ত থাকে।
Spring Security এ CSRF Protection কনফিগারেশন:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/public").permitAll()
.anyRequest().authenticated()
.and()
.csrf(); // CSRF Protection ডিফল্টভাবে সক্রিয়
}
}
CSRF Token HTML ফর্মে যোগ করা:
Spring Security একটি CSRF টোকেন সরবরাহ করে যা ফর্ম সাবমিশনের সময় পাঠানো হয়।
<form action="/submit" method="post">
<input type="hidden" name="_csrf" value="${_csrf.token}" />
<button type="submit">Submit</button>
</form>
CSRF Token Access করতে:
Spring Security সরবরাহিত CSRF টোকেনটি থাইমলিফ বা সরাসরি API তে ব্যবহার করা যায়।
<meta name="_csrf" content="${_csrf.token}">
<meta name="_csrf_header" content="${_csrf.headerName}">
CSRF Protection API রিকোয়েস্টের জন্য:
- CSRF টোকেন হেডারে অন্তর্ভুক্ত করা: ক্লায়েন্টের (যেমন, React, Angular) API রিকোয়েস্টে CSRF টোকেন যোগ করতে হবে।
const csrfToken = document.querySelector('meta[name="_csrf"]').getAttribute('content');
const csrfHeader = document.querySelector('meta[name="_csrf_header"]').getAttribute('content');
fetch('/api/endpoint', {
method: 'POST',
headers: {
[csrfHeader]: csrfToken,
'Content-Type': 'application/json'
},
body: JSON.stringify({ data: 'value' })
});
- CSRF Protection নিষ্ক্রিয় করা (যদি প্রয়োজন হয়): কিছু ক্ষেত্রে (যেমন, শুধুমাত্র API-এর জন্য ব্যবহার), CSRF Protection নিষ্ক্রিয় করা যেতে পারে।
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable() // CSRF Protection নিষ্ক্রিয়
.authorizeRequests()
.antMatchers("/api/**").permitAll()
.anyRequest().authenticated();
}
}
Spring Security এ CSRF Protection এর সুবিধা:
- Cross-Site Attacks প্রতিরোধ:
- Spring Security নিশ্চিত করে যে প্রতিটি সংবেদনশীল রিকোয়েস্টে একটি বৈধ টোকেন প্রয়োজন।
- Automatic Token Generation:
- Spring Security স্বয়ংক্রিয়ভাবে CSRF টোকেন তৈরি এবং যাচাই করে।
- Customizable Configuration:
- প্রয়োজন অনুযায়ী CSRF Protection কাস্টমাইজ করা যায়।
CSRF Protection এর চ্যালেঞ্জ এবং সমাধান:
- API Only Applications:
- যদি অ্যাপ্লিকেশন কেবল API-এর উপর ভিত্তি করে হয় এবং শুধুমাত্র টোকেন ভিত্তিক Authentication ব্যবহার করে, তাহলে CSRF Protection নিষ্ক্রিয় করা যেতে পারে।
- Stateful vs Stateless Application:
- Stateless অ্যাপ্লিকেশনে (যেমন JWT বা OAuth ব্যবহার করা হলে), CSRF Protection এর প্রয়োজন হয় না।
CSRF vs XSS (Cross-Site Scripting):
| CSRF | XSS |
|---|---|
| ব্যবহারকারীর সেশনের দুর্বলতা ব্যবহার করে। | ব্রাউজার এবং ক্লায়েন্ট সাইড কোডে আক্রমণ করে। |
| সঠিক টোকেন প্রয়োজন। | আক্রমণকারী স্ক্রিপ্ট ইনজেক্ট করে। |
| ব্যবহারকারীকে ভুল কাজ সম্পন্ন করতে প্ররোচিত করে। | ডেটা চুরি বা সিস্টেম ম্যানিপুলেট করে। |
CSRF সুরক্ষার গুরুত্ব:
CSRF আক্রমণ সিস্টেমের নিরাপত্তা ঝুঁকি বাড়ায়। Spring Security এর বিল্ট-ইন CSRF Protection ওয়েব অ্যাপ্লিকেশনের সুরক্ষার একটি অপরিহার্য অংশ। এটি ব্যবহার করে নিরাপদ অ্যাপ্লিকেশন তৈরি করা সহজ হয়।
CSRF (Cross-Site Request Forgery) হল একটি সাধারণ ওয়েব নিরাপত্তা আক্রমণ যেখানে একটি দুষ্টু ওয়েবসাইট ব্যবহারকারীর ব্রাউজারে অন্য ওয়েবসাইটে অননুমোদিত অনুরোধ পাঠায় যেখানে ব্যবহারকারী ইতিমধ্যেই লগইন করেছেন। Spring Security ডিফল্টভাবে CSRF Protection সক্রিয় রাখে, যা এমন আক্রমণ প্রতিরোধে সাহায্য করে।
1. CSRF Protection কিভাবে কাজ করে?
CSRF Protection মূলত একটি CSRF Token এর মাধ্যমে কাজ করে।
- Spring Security একটি Random Token তৈরি করে এবং এটি HTTP Request এর সাথে যাচাই করে।
- এই Token সাধারণত একটি Hidden Field হিসাবে ফর্মের সাথে পাঠানো হয় বা HTTP Header এ যুক্ত হয়।
- যদি টোকেন মেল না খায়, তাহলে Spring Security অনুরোধটি ব্লক করে।
2. Spring Security তে CSRF Protection ডিফল্ট কনফিগারেশন
Spring Security CSRF Protection ডিফল্টভাবে সক্রিয়। তাই কোনো অতিরিক্ত কনফিগারেশন প্রয়োজন হয় না যদি এটি ডিফল্ট ব্যবহার করা হয়।
Example Configuration:
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.csrf(); // Default CSRF Protection enabled
}
}
3. CSRF Token ব্যবহার এবং ফ্রন্টএন্ডে পাঠানো
CSRF Token ফ্রন্টএন্ড বা ফর্মে পাঠানোর জন্য Spring Security দুটি পদ্ধতি সরবরাহ করে:
Hidden Field (HTML Form): CSRF টোকেনটি একটি Hidden Field হিসাবে পাঠানো হয়।
উদাহরণ (Thymeleaf):
<form action="/submit" method="post"> <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" /> <button type="submit">Submit</button> </form>HTTP Header (AJAX): যদি API বা AJAX কলের জন্য CSRF Protection প্রয়োজন হয়, তাহলে টোকেন HTTP Header এ পাঠাতে হবে।
উদাহরণ (JavaScript):
const csrfToken = document.querySelector('meta[name="_csrf"]').content; const csrfHeader = document.querySelector('meta[name="_csrf_header"]').content; fetch('/api/submit', { method: 'POST', headers: { [csrfHeader]: csrfToken, 'Content-Type': 'application/json' }, body: JSON.stringify({ data: "example" }) });এখানে টোকেন মেটা ট্যাগ থেকে পাওয়া যেতে পারে:
<meta name="_csrf" content="${_csrf.token}" /> <meta name="_csrf_header" content="${_csrf.headerName}" />
4. CSRF Protection কাস্টমাইজেশন
i. CSRF নিষ্ক্রিয় করা (API এর জন্য):
CSRF Protection API এর ক্ষেত্রে সাধারণত নিষ্ক্রিয় রাখা হয়, কারণ API-তে stateful session ব্যবহার হয় না।
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable() // Disable CSRF for APIs
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic(); // For basic authentication
}
ii. নির্দিষ্ট URL এর জন্য CSRF বাদ দেওয়া:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.ignoringAntMatchers("/api/**") // Ignore CSRF for specific endpoints
.and()
.authorizeRequests()
.anyRequest().authenticated();
}
5. Custom CSRF Token Repository
Spring Security ডিফল্ট HttpSessionCsrfTokenRepository ব্যবহার করে টোকেন সংরক্ষণের জন্য। এটি কাস্টমাইজ করা সম্ভব।
import org.springframework.security.web.csrf.CsrfToken;
import org.springframework.security.web.csrf.CsrfTokenRepository;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class CustomCsrfTokenRepository implements CsrfTokenRepository {
@Override
public CsrfToken generateToken(HttpServletRequest request) {
return new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", UUID.randomUUID().toString());
}
@Override
public void saveToken(CsrfToken token, HttpServletRequest request, HttpServletResponse response) {
// Custom logic to save the token
}
@Override
public CsrfToken loadToken(HttpServletRequest request) {
// Custom logic to load the token
return null;
}
}
কাস্টম রেপোসিটরি Spring Security কনফিগারেশনে যুক্ত করা:
http
.csrf()
.csrfTokenRepository(new CustomCsrfTokenRepository());
6. CSRF Token Validation Failure Handling
CSRF টোকেন যাচাই ব্যর্থ হলে কাস্টম হ্যান্ডলার যোগ করতে পারেন:
import org.springframework.security.web.csrf.CsrfAuthenticationStrategy;
import org.springframework.security.web.csrf.CsrfException;
import org.springframework.security.web.csrf.InvalidCsrfTokenException;
import org.springframework.security.web.csrf.MissingCsrfTokenException;
@Configuration
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException {
if (accessDeniedException instanceof MissingCsrfTokenException) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "CSRF Token Missing!");
} else if (accessDeniedException instanceof InvalidCsrfTokenException) {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Invalid CSRF Token!");
} else {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied!");
}
}
}
7. Spring Security CSRF Protection এর Best Practices
- API এর ক্ষেত্রে CSRF Protection নিষ্ক্রিয় রাখুন: API-তে সাধারণত stateless authentication (JWT) ব্যবহৃত হয়।
- CSRF Token সবসময় ব্যবহার করুন: HTML ফর্ম সাবমিশনের জন্য।
- Custom Error Pages যোগ করুন: যাতে ব্যবহারকারী স্পষ্ট ত্রুটি বার্তা পায়।
- HTTP Headers নিশ্চিত করুন: AJAX এবং API কলের জন্য।
8. উপসংহার
CSRF Protection হল Spring Security এর একটি গুরুত্বপূর্ণ বৈশিষ্ট্য যা অননুমোদিত অনুরোধ প্রতিরোধ করতে সাহায্য করে। ডিফল্ট কনফিগারেশন অনেক ক্ষেত্রেই যথেষ্ট হলেও, প্রয়োজন অনুযায়ী এটি কাস্টমাইজ করা যায়। নিরাপত্তা বাড়ানোর জন্য CSRF Protection সর্বদা সচল রাখা উচিত, বিশেষ করে stateful ওয়েব অ্যাপ্লিকেশনগুলির জন্য।
Spring Security CSRF (Cross-Site Request Forgery) আক্রমণ প্রতিরোধের জন্য একটি বিল্ট-ইন সুরক্ষা প্রদান করে। এটি প্রতিটি HTTP POST, PUT, DELETE, ইত্যাদি অনুরোধের জন্য একটি CSRF টোকেন যাচাই করে। তবে, যদি আপনাকে এই প্রক্রিয়া কাস্টমাইজ করতে হয়, যেমন Custom CSRF Token তৈরি বা Exception Handling প্রয়োগ করতে হয়, তাহলে নিম্নলিখিত ধাপগুলো অনুসরণ করা যেতে পারে।
Custom CSRF Token তৈরি
১. Custom CSRF Token Generator
Spring Security-তে ডিফল্টভাবে CsrfToken ব্যবহার করা হয়। আপনি যদি নিজস্ব কাস্টম টোকেন প্রয়োগ করতে চান, তাহলে একটি কাস্টম CsrfToken ক্লাস এবং টোকেন জেনারেটর তৈরি করতে হবে।
Custom CsrfToken ক্লাস
import org.springframework.security.web.csrf.CsrfToken;
public class CustomCsrfToken implements CsrfToken {
private final String token;
private final String parameterName;
private final String headerName;
public CustomCsrfToken(String token, String parameterName, String headerName) {
this.token = token;
this.parameterName = parameterName;
this.headerName = headerName;
}
@Override
public String getHeaderName() {
return headerName;
}
@Override
public String getParameterName() {
return parameterName;
}
@Override
public String getToken() {
return token;
}
}
Custom Token Repository
Spring Security-তে CsrfTokenRepository ইন্টারফেস ইমপ্লিমেন্ট করে একটি কাস্টম টোকেন স্টোর করতে পারেন।
import org.springframework.security.web.csrf.CsrfToken;
import org.springframework.security.web.csrf.CsrfTokenRepository;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;
public class CustomCsrfTokenRepository implements CsrfTokenRepository {
@Override
public CsrfToken generateToken(HttpServletRequest request) {
String token = UUID.randomUUID().toString(); // Custom token logic
return new CustomCsrfToken(token, "_csrf", "X-CSRF-TOKEN");
}
@Override
public void saveToken(CsrfToken token, HttpServletRequest request, HttpServletResponse response) {
// Save token in session or cookie
if (token == null) {
request.getSession().removeAttribute("_csrf");
} else {
request.getSession().setAttribute("_csrf", token);
}
}
@Override
public CsrfToken loadToken(HttpServletRequest request) {
return (CsrfToken) request.getSession().getAttribute("_csrf");
}
}
২. Spring Security Configuration-এ Custom CSRF যুক্ত করা
Spring Security-তে কাস্টম CsrfTokenRepository যুক্ত করতে নিচের মতো configuration ব্যবহার করুন:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf()
.csrfTokenRepository(new CustomCsrfTokenRepository()) // Custom CSRF Token
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin();
return http.build();
}
}
Custom CSRF Exception Handling
Spring Security CsrfException ছুঁড়ে দেয় যদি CSRF টোকেন বৈধ না হয়। আপনি কাস্টম exception handling প্রয়োগ করে এটি কাস্টমাইজ করতে পারেন।
১. Custom Access Denied Handler
AccessDeniedHandler ইন্টারফেস ইমপ্লিমেন্ট করে একটি কাস্টম handler তৈরি করুন:
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException)
throws IOException, ServletException {
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
response.getWriter().write("CSRF token validation failed: " + accessDeniedException.getMessage());
}
}
২. Spring Security Configuration-এ Exception Handler যুক্ত করা
Security configuration-এ কাস্টম exception handler যুক্ত করুন:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.csrf.CsrfFilter;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf()
.csrfTokenRepository(new CustomCsrfTokenRepository())
.and()
.exceptionHandling()
.accessDeniedHandler(new CustomAccessDeniedHandler()) // Custom handler
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin();
return http.build();
}
}
৩. Custom Exception Message বা JSON Response
JSON response প্রদান করতে CustomAccessDeniedHandler এ নিম্নলিখিত কোড যোগ করুন:
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException)
throws IOException, ServletException {
response.setContentType("application/json");
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
response.getWriter().write("{\"error\": \"CSRF token validation failed\", \"message\": \""
+ accessDeniedException.getMessage() + "\"}");
}
৪. Global Exception Handling (Optional)
Spring MVC এর মাধ্যমে Global Exception Handling প্রয়োগ করতে পারেন:
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.security.web.csrf.CsrfException;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(CsrfException.class)
public ResponseEntity<String> handleCsrfException(CsrfException ex) {
return new ResponseEntity<>("CSRF validation error: " + ex.getMessage(), HttpStatus.FORBIDDEN);
}
}
উপসংহার
Spring Security-তে Custom CSRF Token এবং Exception Handling কাস্টমাইজেশন আপনাকে নিরাপত্তা আরও শক্তিশালী এবং ব্যবহারকারীর অভিজ্ঞতা উন্নত করতে সাহায্য করে।
- Custom CSRF Token আপনার নির্দিষ্ট নিরাপত্তা প্রয়োজন মেটাতে ব্যবহার করা যেতে পারে।
- Custom Exception Handling ব্যবহারকারীদের জন্য সুনির্দিষ্ট এবং পরিষ্কার error messages প্রদান করে।
এই পদ্ধতিগুলি অনুসরণ করে আপনি Spring Security-তে উন্নত সুরক্ষা প্রয়োগ করতে পারেন।
CSRF (Cross-Site Request Forgery) কি?
CSRF (Cross-Site Request Forgery) একটি ওয়েব নিরাপত্তা আক্রমণ, যেখানে একটি ব্যবহারকারী না জেনেই নিজের ব্রাউজার থেকে অনিচ্ছাকৃতভাবে হ্যাকারদের উদ্দেশ্যে অনুরোধ পাঠায়। উদাহরণস্বরূপ, একটি ম্যালিসিয়াস লিঙ্কে ক্লিক করলে ব্যবহারকারীর লগইন সেশনের অধীনে ক্ষতিকর কাজ করা সম্ভব।
Spring Security-তে CSRF Protection ডিফল্টভাবে সক্রিয় থাকে, যা এই ধরনের আক্রমণ প্রতিরোধে সাহায্য করে।
CSRF Protection-এর মূল বৈশিষ্ট্য
- CSRF Protection সক্রিয় থাকলে, প্রতিটি HTTP POST, PUT, DELETE ইত্যাদি অনুরোধের সঙ্গে একটি CSRF টোকেন সরবরাহ করতে হবে।
- Spring Security একটি CSRF টোকেন জেনারেট করে এবং তা ক্লায়েন্ট সাইডে কুকি বা Hidden Form Field-এ সংরক্ষণ করে।
- CSRF টোকেন যাচাই করার মাধ্যমে অননুমোদিত অনুরোধ প্রতিরোধ করা যায়।
Spring Security-তে CSRF Protection বাস্তবায়ন
1. Spring Security Dependency
Spring Boot প্রকল্পে spring-boot-starter-security ডিপেন্ডেন্সি যোগ করুন।
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2. CSRF Protection কনফিগারেশন
Spring Security-এর CSRF Protection ডিফল্টভাবে সক্রিয় থাকে। তবে, আপনি কনফিগারেশন কাস্টমাইজ করতে পারেন।
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/public/**").permitAll() // পাবলিক এন্ডপয়েন্ট সবার জন্য উন্মুক্ত
.anyRequest().authenticated() // অন্য সব এন্ডপয়েন্টে প্রমাণীকরণ প্রয়োজন
.and()
.csrf() // CSRF Protection সক্রিয়
.and()
.formLogin(); // ফর্ম ভিত্তিক লগইন সক্রিয়
return http.build();
}
}
3. CSRF Token সংগ্রহ ও পাঠানো
HTML ফর্মের ক্ষেত্রে:
Spring Security thymeleaf বা অন্য টেমপ্লেট ইঞ্জিন ব্যবহার করলে, Hidden Field এর মাধ্যমে CSRF টোকেন পাঠানো যায়।
<form action="/submit" method="post">
<input type="hidden" name="_csrf" value="${_csrf.token}" />
<button type="submit">Submit</button>
</form>
AJAX অনুরোধের ক্ষেত্রে:
AJAX অনুরোধ পাঠানোর সময় CSRF টোকেন হেডারে যোগ করতে হবে।
// CSRF টোকেন সংগ্রহ
const csrfToken = document.querySelector('meta[name="_csrf"]').content;
// AJAX অনুরোধ
fetch('/submit', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': csrfToken // CSRF টোকেন হেডারে যোগ
},
body: JSON.stringify({ name: "John Doe" })
}).then(response => {
console.log(response);
});
4. CSRF Token-সহ একটি উদাহরণ
Controller:
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
@RestController
@RequestMapping("/")
public class AppController {
@GetMapping("/form")
public ModelAndView showForm() {
return new ModelAndView("form"); // form.html ফাইলটি রিটার্ন করবে
}
@PostMapping("/submit")
public String handleSubmit(@RequestParam String name) {
return "Submitted Name: " + name;
}
}
HTML ফর্ম (form.html):
<!DOCTYPE html>
<html>
<head>
<meta name="_csrf" content="${_csrf.token}">
</head>
<body>
<h1>Submit Your Name</h1>
<form action="/submit" method="post">
<input type="text" name="name" placeholder="Enter your name">
<input type="hidden" name="_csrf" value="${_csrf.token}">
<button type="submit">Submit</button>
</form>
</body>
</html>
CSRF Protection নিষ্ক্রিয় করার পদ্ধতি (শিক্ষামূলক উদ্দেশ্যে)
যদি আপনার কোনো বিশেষ ক্ষেত্রে CSRF Protection নিষ্ক্রিয় করতে হয় (যেমন API এর ক্ষেত্রে যেখানে JWT ব্যবহার করা হয়), নিচের পদ্ধতি অনুসরণ করুন:
http
.csrf().disable() // CSRF Protection নিষ্ক্রিয়
.authorizeRequests()
.anyRequest().authenticated();
নোট: CSRF Protection নিষ্ক্রিয় করা হলে, সিস্টেম নিরাপত্তার ঝুঁকিতে পড়তে পারে। শুধুমাত্র প্রয়োজনীয় ক্ষেত্রেই এটি নিষ্ক্রিয় করুন।
CSRF Protection-এর সেরা চর্চা
- CSRF Protection সক্রিয় রাখুন:
- Spring Security-তে CSRF Protection ডিফল্টভাবে সক্রিয় থাকে। এটিকে অকারণে নিষ্ক্রিয় করবেন না।
- API-এর ক্ষেত্রে বিকল্প Authentication পদ্ধতি ব্যবহার করুন:
- JWT (JSON Web Token) বা OAuth2 ব্যবহার করলে CSRF টোকেনের প্রয়োজন নেই।
- Secure Cookies:
- CSRF টোকেন কুকিতে সংরক্ষণ করলে, এটি
SecureএবংHttpOnlyপ্রোপার্টি সহ ব্যবহার করুন।
- CSRF টোকেন কুকিতে সংরক্ষণ করলে, এটি
- CORS (Cross-Origin Resource Sharing):
- নির্দিষ্ট ডোমেইন থেকে অনুরোধ গ্রহণ করতে CORS কনফিগার করুন।
উপসংহার
Spring Security-র CSRF Protection Cross-Site Request Forgery আক্রমণ প্রতিরোধে অত্যন্ত কার্যকর। ডিফল্টভাবে এটি সক্রিয় থাকে এবং এর ব্যবহার সহজ। উদাহরণগুলো অনুসরণ করে ফর্ম বা AJAX অনুরোধের সাথে CSRF টোকেন সংযুক্ত করে নিরাপত্তা নিশ্চিত করা যায়।
Read more